#-----------------------------#
# coding='utf-8'
# !Python3
# 使用 SQLAlchemy 创建数据库程序
#-----------------------------#

from flask import Flask
from constants import DB_URI
""" from sqlalchemy import create_engine
from sqlalchemy import Column,Integer,String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship """

from flask_sqlalchemy import SQLAlchemy


app = Flask(__name__) 

#建立引擎>建立模型/映射
#把表映射成类，把行作实例，把字段作属性
#engine=create_engine(DB_URI,echo=False) #创建数据库引擎，true可以回显执行的底层sql语句

#region --epic-1 build connections
""" with engine.connect() as con:
    # rs=con.execute('Select 1')
    # print (rs.fetchone())

    #使用原生sql
    con.execute('drop table if exists users')
    con.execute('create table users(id int primary key auto_increment,name varchar(25))')
    con.execute('insert into users(name) values ("xiaoMing")')
    con.execute('insert into users(name) values ("xiaoMa")  ')
    #rs=con.execute('show tables')
    #print(rs)
    rs=con.execute('select * from users')
    for i in rs:
        print(i) """
    
#endregion 

#region --epic-2  build ORM 

# 所有的类都要继承自`declarative_base`这个函数生成的基类
# SQLAlchemy会自动的设置第一个Integer的主键并且没有被标记为外键的字段添加自增长的属性
Base = declarative_base(engine)
class User(Base):
        # 定义表名为users
        __tablename__ = 'users'
        id = Column(Integer,primary_key=True)    # 将id设置为主键，并且默认是自增长的
        name = Column(String(50))                # name字段，字符类型，最大的长度是50个字符
        fullname = Column(String(50))
        sex=Column(Integer,default=0,nullable=False)            # 1 male,2 female, 0,unknown
        password = Column(String(100)) 
        # 在ORM层面绑定和`Address`表的关系
        addresses = relationship("Address",order_by=Address.id,back_populates="user")
        # 让打印出来的数据更好看，可选的
        def __repr__(self):
            return "<User(id='%s',name='%s',sex='%s',fullname='%s',password='%s')>" % (self.id,self.name,self.sex,self.fullname,self.password)

class Address(Base):
        __tablename__ = 'address'
        id = Column(Integer,primary_key=True)
        email_addr = Column(String,nullable=False)
        # User表的外键，指定外键的时候，是使用的是数据库表的名称，而不是类名
        user_id = Column(Integer,ForeignKey('users.id'))
        # 在ORM层面绑定两者之间的关系，第一个参数是绑定的表的类名，
        # 第二个参数back_populates是通过User反向访问时的字段名称
        user = relationship('User',back_populates="addresses")

        def __repr__(self):
            return "<Address(email_addr='%s')>" % self.email_address
# 执行映射到数据库   
Base.metadata.create_all()

#建立Session对象和数据库去打交道
Session=sessionmaker(bind=engine)
session=Session()

#endregion

#region --操作数据库
    #1 在SQLAlchemy的ORM实现中，在做commit操作之前，所有的操作都是在事务中进行的，
       # 因此如果你要将事务中的操作真正的映射到数据库中，还需要做commit操作。
    #2 查找操作是通过session.query()方法实现的，这个方法会返回一个Query对象，
        #Query对象相当于一个数组，装载了查找出来的数据，并且可以进行迭代。
    #3 如果想对结果进行过滤，可以使用filter_by和filter两个方法，这两个方法都是用来做过滤的，
        # 区别在于，filter_by是传入关键字参数，filter是传入条件判断，并且filter能够传入的条件更多更灵活，
#增加一个用户
# ed_user = User(name='ed',fullname='Ed Jones',password='edspassword')
# session.add(ed_user) # 把数据添加到session
# session.commit()     # 把数据存储到数据库
# print(ed_user)

# 查询所有用户实例
""" for instance in session.query(User).order_by(User.id):
    print (instance) """

# 使用过滤器查询指定用户
""" for name in session.query(User.name).filter_by(fullname='Ed Jones'):
    print (name)

s=session.query(User.sex).filter(User.name=='ed',User.fullname=='Ed Jones')
print(s) """

#endregion
